package com.zlyx.easy.core.spring;

import java.lang.annotation.Annotation;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;

import com.zlyx.easy.core.annotations.SpringBean;
import com.zlyx.easy.core.map.Maps;
import com.zlyx.easy.core.reflect.ProxyUtils;

/**
 * @Auth 赵光
 * @Describle
 * @2018年12月27日 上午9:17:57
 */
@SpringBean(todo = { "上下文工具" })
public class SpringUtils implements ApplicationContextAware {

	protected static ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext context) {
		SpringUtils.applicationContext = context;
	}

	public static ApplicationContext getApplicationContext() {
		return SpringUtils.applicationContext;
	}

	public static void publish(ApplicationEvent event) {
		if (getApplicationContext() != null) {
			getApplicationContext().publishEvent(event);
		}
	}

	/**
	 * 根据name查找bean
	 * 
	 * @param <T>
	 * @param beanName
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String beanName) {
		return applicationContext == null ? null : (T) applicationContext.getBean(beanName);
	}

	/**
	 * 包含bean
	 * 
	 * @param beanName
	 * @return
	 */
	public static boolean containsBean(String beanName) {
		return applicationContext == null ? false : applicationContext.containsBean(beanName);
	}

	/**
	 * 获取bean类型
	 * 
	 * @param beanName
	 * @return
	 */
	public static Class<?> getBeanClass(String beanName) {
		return applicationContext == null ? null : getBean(beanName).getClass();
	}

	/**
	 * 根据注解查找bean
	 * 
	 * @param annotation
	 * @return
	 */
	public static Map<String, Object> getBeanswithAnnotation(Class<? extends Annotation> annotation) {
		return annotation == null || applicationContext == null ? null
				: applicationContext.getBeansWithAnnotation(annotation);
	}

	/**
	 * 根据类型获取bean
	 * 
	 * @param <T>
	 * @param beanSuperClass
	 * @return
	 */
	public static <T> Map<String, T> getBeansOfType(Class<T> beanSuperClass) {
		return applicationContext == null ? null : applicationContext.getBeansOfType(beanSuperClass);
	}

	/**
	 * 根据注解类型或父类类型获取bean
	 * 
	 * @param <T>
	 * @param cls
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T> Map<Class<?>, Object> getBeanMapByCls(Class<?> cls) throws Exception {
		Map<Class<?>, Object> beanMap = Maps.newMap();
		Map<String, Object> beans = null;
		Object target = null;
		Class<?> targetClass = null;
		if (cls.isAnnotation()) {
			beans = getBeanswithAnnotation((Class<? extends Annotation>) cls);
		} else {
			beans = (Map<String, Object>) getBeansOfType(cls);
		}
		if (beans == null || beans.isEmpty()) {
			return beanMap;
		}
		for (Entry<String, ?> entry : beans.entrySet()) {
			target = ProxyUtils.getTarget(entry.getValue());
			targetClass = target.getClass();
			if (target instanceof Proxy) {
				targetClass = entry.getValue().getClass().getInterfaces()[0];
				beanMap.put(targetClass, target);
			} else if (targetClass.getInterfaces().length > 0) {
				beanMap.put(targetClass.getInterfaces()[0], target);
			} else {
				beanMap.put(targetClass, target);
			}
		}
		return beanMap;
	}

}
